#include "./../inc/main.h"

/* 游戏逻辑 */

ChessGame::ChessGame(GameMode mode)
    : currentMode(mode), gameOver(false), currentPlayer(Red),
      board(BOARD_COLS, std::vector<ChessPiece *>(BOARD_ROWS, nullptr)),
      selectedPiece(-1, -1), hasSelectedPiece(false),
      message(""), messageStartTime(0)
{
}

ChessGame::~ChessGame()
{
    // 释放棋盘上的棋子
    for (auto &row : board)
    {
        for (auto &piece : row)
        {
            if (piece)
                delete piece;
        }
    }
}

ChessGame::ChessGame(const ChessGame &other)
{
    // 实现棋盘深拷贝逻辑
    currentMode = other.currentMode;
    gameOver = other.gameOver;
    currentPlayer = other.currentPlayer;
    selectedPiece = other.selectedPiece;
    hasSelectedPiece = other.hasSelectedPiece;
    message = other.message;
    messageStartTime = other.messageStartTime;

    // 深拷贝棋子
    board.resize(BOARD_COLS, std::vector<ChessPiece *>(BOARD_ROWS, nullptr));
    for (int i = 0; i < BOARD_COLS; ++i)
    {
        for (int j = 0; j < BOARD_ROWS; ++j)
        {
            if (other.board[i][j])
            {
                // 根据棋子类型创建新实例
                board[i][j] = ChessPieceFactory::createPiece(
                    other.board[i][j]->getType(),
                    other.board[i][j]->getPieceColor(),
                    i, j);
            }
        }
    }
}

void ChessGame::initBoard()
{
    // 清空棋盘
    for (auto &row : board)
    {
        for (auto &piece : row)
        {
            if (piece)
            {
                delete piece;
                piece = nullptr;
            }
        }
    }

    // 初始化红方棋子（上方）
    board[0][0] = ChessPieceFactory::createPiece(Chariot, Red, 0, 0);
    board[1][0] = ChessPieceFactory::createPiece(Horse, Red, 1, 0);
    board[2][0] = ChessPieceFactory::createPiece(Elephant, Red, 2, 0);
    board[3][0] = ChessPieceFactory::createPiece(Advisor, Red, 3, 0);
    board[4][0] = ChessPieceFactory::createPiece(King, Red, 4, 0);
    board[5][0] = ChessPieceFactory::createPiece(Advisor, Red, 5, 0);
    board[6][0] = ChessPieceFactory::createPiece(Elephant, Red, 6, 0);
    board[7][0] = ChessPieceFactory::createPiece(Horse, Red, 7, 0);
    board[8][0] = ChessPieceFactory::createPiece(Chariot, Red, 8, 0);

    // 红方炮
    board[1][2] = ChessPieceFactory::createPiece(Cannon, Red, 1, 2);
    board[7][2] = ChessPieceFactory::createPiece(Cannon, Red, 7, 2);

    // 红方兵
    board[0][3] = ChessPieceFactory::createPiece(Pawn, Red, 0, 3);
    board[2][3] = ChessPieceFactory::createPiece(Pawn, Red, 2, 3);
    board[4][3] = ChessPieceFactory::createPiece(Pawn, Red, 4, 3);
    board[6][3] = ChessPieceFactory::createPiece(Pawn, Red, 6, 3);
    board[8][3] = ChessPieceFactory::createPiece(Pawn, Red, 8, 3);

    // 黑方兵
    board[0][6] = ChessPieceFactory::createPiece(Pawn, Black, 0, 6);
    board[2][6] = ChessPieceFactory::createPiece(Pawn, Black, 2, 6);
    board[4][6] = ChessPieceFactory::createPiece(Pawn, Black, 4, 6);
    board[6][6] = ChessPieceFactory::createPiece(Pawn, Black, 6, 6);
    board[8][6] = ChessPieceFactory::createPiece(Pawn, Black, 8, 6);

    // 黑方炮
    board[1][7] = ChessPieceFactory::createPiece(Cannon, Black, 1, 7);
    board[7][7] = ChessPieceFactory::createPiece(Cannon, Black, 7, 7);

    // 黑方棋子（下方）
    board[0][9] = ChessPieceFactory::createPiece(Chariot, Black, 0, 9);
    board[1][9] = ChessPieceFactory::createPiece(Horse, Black, 1, 9);
    board[2][9] = ChessPieceFactory::createPiece(Elephant, Black, 2, 9);
    board[3][9] = ChessPieceFactory::createPiece(Advisor, Black, 3, 9);
    board[4][9] = ChessPieceFactory::createPiece(King, Black, 4, 9);
    board[5][9] = ChessPieceFactory::createPiece(Advisor, Black, 5, 9);
    board[6][9] = ChessPieceFactory::createPiece(Elephant, Black, 6, 9);
    board[7][9] = ChessPieceFactory::createPiece(Horse, Black, 7, 9);
    board[8][9] = ChessPieceFactory::createPiece(Chariot, Black, 8, 9);
}

void ChessGame::displayBoard(Lcd *lcd)
{
    int *buffer = lcd->getBuffer();
    memset(buffer, 0, LCD_WIDTH * LCD_HEIGHT * sizeof(int));

    // 显示棋盘背景
    BMP bg("./res/chess.bmp");
    bg.show(buffer);

    // 显示所有棋子
    for (int i = 0; i < BOARD_COLS; ++i)
    {
        for (int j = 0; j < BOARD_ROWS; ++j)
        {
            if (board[i][j] != nullptr)
            {
                int screenX, screenY;
                boardToScreen(i, j, screenX, screenY);

                string imagePath = getPieceImagePath(board[i][j]);
                if (!imagePath.empty())
                {
                    try
                    {
                        BMP pieceImage(imagePath.c_str());
                        int pieceCenterX = screenX + GRID_SIZE / 2;
                        int pieceCenterY = screenY + GRID_SIZE / 2;
                        showRotatedImage(pieceImage, buffer, pieceCenterX, pieceCenterY);

                        // 绘制棋子边框
                        int circleColor = (board[i][j]->getPieceColor() == Red) ? ShowFont::red : ShowFont::black;
                        BMP::drawCircle(buffer, pieceCenterX, pieceCenterY, 25, circleColor);
                        BMP::drawCircle(buffer, pieceCenterX, pieceCenterY, 26, circleColor);

                        if (hasSelectedPiece && i == selectedPiece.x() && j == selectedPiece.y())
                        {
                            // 绘制额外的高亮圆圈
                            BMP::drawCircle(buffer, pieceCenterX, pieceCenterY, 23, 0x00FFFF); // 青色高亮
                            BMP::drawCircle(buffer, pieceCenterX, pieceCenterY, 24, 0x00FFFF);
                            BMP::drawCircle(buffer, pieceCenterX, pieceCenterY, 27, 0x00FFFF);
                            BMP::drawCircle(buffer, pieceCenterX, pieceCenterY, 28, 0x00FFFF);
                        }
                    }
                    catch (...)
                    {
                        cout << "图片加载失败: " << imagePath << endl;
                    }
                }
            }
        }
    }

    // 绘制消息
    drawMessage(lcd);

    lcd->swapBuffers();
}

// 处理触摸事件
void ChessGame::handleTouch(Point &touchPoint, Lcd *lcd)
{
    int boardX, boardY;

    // 转换触摸坐标到棋盘坐标
    screenToBoard(touchPoint.x(), touchPoint.y(), boardX, boardY);

    // 检查坐标是否有效
    if (boardX < 0 || boardX >= BOARD_COLS || boardY < 0 || boardY >= BOARD_ROWS)
    {
        return;
    }

    // 如果已经选中了一个棋子
    if (hasSelectedPiece)
    {
        // 如果点击的是已选中的棋子，则取消选中
        if (boardX == selectedPiece.x() && boardY == selectedPiece.y())
        {
            hasSelectedPiece = false;
            selectedPiece.setX(-1);
            selectedPiece.setY(-1);
            displayBoard(lcd); // 重新显示棋盘以取消高亮
            return;
        }

        // 尝试移动棋子
        if (movePiece(selectedPiece.x(), selectedPiece.y(), boardX, boardY, lcd))
        {
            switchPlayer();           // 移动成功则切换玩家
            hasSelectedPiece = false; // 取消选中状态
            selectedPiece.setX(-1);
            selectedPiece.setY(-1);

            // 检查游戏是否结束
            if (isGameOver())
            {
                gameOver = true;
                showMessage(lcd, "游戏结束！");
            }
        }
        else
        {
        }
    }
    // 如果没有选中棋子
    else
    {
        // 检查点击位置是否有棋子且是当前玩家的棋子
        if (board[boardX][boardY] != nullptr &&
            board[boardX][boardY]->getPieceColor() == currentPlayer)
        {
            // 选中该棋子
            selectedPiece.setX(boardX);
            selectedPiece.setY(boardY);
            hasSelectedPiece = true;
            displayBoard(lcd); // 重新显示棋盘以显示高亮
        }
        else if (board[boardX][boardY] != nullptr)
        {
            // 点击了对方棋子
            showMessage(lcd, "请选择自己的棋子");
        }
    }
}

// 将棋盘坐标转换为屏幕坐标
void ChessGame::boardToScreen(int boardX, int boardY, int &screenX, int &screenY)
{
    screenX = BOARD_START_X + boardY * GRID_SIZE;
    screenY = BOARD_START_Y + boardX * GRID_SIZE;
}

// 将屏幕坐标转换为棋盘坐标
void ChessGame::screenToBoard(int screenX, int screenY, int &boardX, int &boardY)
{
    boardX = (screenY - BOARD_START_Y) / GRID_SIZE;
    boardY = (screenX - BOARD_START_X) / GRID_SIZE;

    // 确保坐标在有效范围内
    boardX = max(0, min(BOARD_COLS - 1, boardX));
    boardY = max(0, min(BOARD_ROWS - 1, boardY));
}

// 获取棋子图片路径
string ChessGame::getPieceImagePath(ChessPiece *piece)
{
    if (!piece)
        return "";

    PieceType type = piece->getType();
    PieceColor color = piece->getPieceColor();

    switch (type)
    {
    case Chariot:
        return color == Red ? "./res/redche.bmp" : "./res/blackche.bmp";
    case Horse:
        return color == Red ? "./res/redma.bmp" : "./res/blackma.bmp";
    case Elephant:
        return color == Red ? "./res/redxiang.bmp" : "./res/blackxiang.bmp";
    case Advisor:
        return color == Red ? "./res/redshi.bmp" : "./res/blackshi.bmp";
    case King:
        return color == Red ? "./res/shuai.bmp" : "./res/jiang.bmp";
    case Cannon:
        return color == Red ? "./res/redpao.bmp" : "./res/blackpao.bmp";
    case Pawn:
        return color == Red ? "./res/bing.bmp" : "./res/zu.bmp";
    default:
        return "";
    }
}

//  旋转图片并显示
void ChessGame::showRotatedImage(BMP &image, int *mp, int centerX, int centerY)
{
    int imgWidth = image.width();
    int imgHeight = image.height();

    int startX = centerX - imgHeight / 2;
    int startY = centerY - imgWidth / 2;

    // 旋转90度显示
    for (int y = 0; y < imgHeight; ++y)
    {
        for (int x = 0; x < imgWidth; ++x)
        {
            int srcIndex = (y * imgWidth + x) * 3;
            int newX = startY + imgWidth - x - 1;
            int newY = startX + y;

            if (newX >= 0 && newX < LCD_HEIGHT && newY >= 0 && newY < LCD_WIDTH)
            {
                *(mp + LCD_WIDTH * newX + newY) =
                    (unsigned char)image[srcIndex] |
                    (unsigned char)image[srcIndex + 1] << 8 |
                    (unsigned char)image[srcIndex + 2] << 16;
            }
        }
    }
}

// 移动判断
bool ChessGame::movePiece(int srcX, int srcY, int destX, int destY, Lcd *lcd)
{
    // 边界检查
    if (srcX < 0 || srcX >= BOARD_COLS || srcY < 0 || srcY >= BOARD_ROWS ||
        destX < 0 || destX >= BOARD_COLS || destY < 0 || destY >= BOARD_ROWS)
    {
        if (lcd)
            showMessage(lcd, "坐标越界");
        cout << "移动失败：坐标越界 (" << srcX << "," << srcY << ") -> (" << destX << "," << destY << ")" << endl;
        return false;
    }

    // 检查源位置是否有棋子
    ChessPiece *srcPiece = board[srcX][srcY];
    if (!srcPiece)
    {
        if (lcd)
            showMessage(lcd, "源位置没有棋子");
        cout << "移动失败：源位置没有棋子 (" << srcX << "," << srcY << ")" << endl;
        return false;
    }

    // 检查目标位置是否有己方棋子
    ChessPiece *destPiece = board[destX][destY];
    if (destPiece && destPiece->getPieceColor() == srcPiece->getPieceColor())
    {
        if (lcd)
            showMessage(lcd, "不能移动到自己的棋子上");
        cout << "移动失败：不能移动到自己的棋子上 (" << destX << "," << destY << ")" << endl;
        return false;
    }

    // 检查移动规则
    if (!srcPiece->canMoveTo(Point(destX, destY), board))
    {
        if (lcd)
            showMessage(lcd, "移动不符合规则");
        cout << "移动失败：移动不符合规则 (" << srcX << "," << srcY << ") -> (" << destX << "," << destY << ")" << endl;
        return false;
    }

    // 执行真正的移动
    if (destPiece)
    {
        delete destPiece; // 吃掉对方棋子
    }
    board[destX][destY] = srcPiece;
    board[srcX][srcY] = nullptr;
    srcPiece->setPosition(destX, destY);

    if(currentMode == NetworkGame)
    {
        sendMoveToNetwork(srcX, srcY, destX, destY);
    }

    // 检查是否将军对方
    PieceColor opponentColor = (srcPiece->getPieceColor() == Red) ? Black : Red;
    if (isInCheck(opponentColor))
    {
        if (lcd)
            showMessage(lcd, "将军！");
    }
    return true;
}

// 重置
void ChessGame::reset()
{
    gameOver = false;
    currentPlayer = Red;
    initBoard();
}

// 模拟移动
bool ChessGame::simulateMove(int srcX, int srcY, int destX, int destY)
{
    if (movePiece(srcX, srcY, destX, destY, nullptr))
    {
        switchPlayer();
        return true;
    }
    return false;
}

// 获取将/帅的位置
Point ChessGame::findKingPosition(PieceColor color)
{
    auto &gameBoard = board;
    for (int x = 0; x < BOARD_COLS; ++x)
    {
        for (int y = 0; y < BOARD_ROWS; ++y)
        {
            ChessPiece *piece = gameBoard[x][y];
            if (piece && piece->getType() == King && piece->getPieceColor() == color)
            {
                return Point(x, y);
            }
        }
    }
    return Point(-1, -1); // 未找到（将/帅被吃）
}

// 检查是否将军
bool ChessGame::isInCheck(PieceColor color)
{
    Point kingPos = findKingPosition(color);
    if (kingPos.x() == -1)
        return false; // 将/帅已被吃

    PieceColor enemyColor = (color == Red) ? Black : Red;

    // 检查对方所有棋子是否能攻击到将/帅
    for (int x = 0; x < BOARD_COLS; ++x)
    {
        for (int y = 0; y < BOARD_ROWS; ++y)
        {
            ChessPiece *piece = board[x][y];
            if (piece && piece->getPieceColor() == enemyColor)
            {
                if (piece->canMoveTo(kingPos, board))
                {
                    return true; // 被将军
                }
            }
        }
    }
    return false;
}

// 检查游戏是否结束
bool ChessGame::isGameOver()
{
    // 检查红方帅或黑方将是否存在
    Point redKingPos = findKingPosition(Red);
    Point blackKingPos = findKingPosition(Black);

    // 如果任一方的将/帅被吃掉，游戏结束
    if (redKingPos.x() == -1 || blackKingPos.x() == -1)
    {
        return true;
    }

    return false;
}

// 获取当前时间(毫秒)
long getCurrentTimeMillis()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

// 显示消息
void ChessGame::showMessage(Lcd *lcd, const string &msg)
{
    message = msg;
    messageStartTime = getCurrentTimeMillis();
    displayBoard(lcd); // 立即刷新显示
}

// 绘制消息到屏幕
void ChessGame::drawMessage(Lcd *lcd)
{
    // 如果没有消息或消息已超时，则不显示
    if (message.empty() || (getCurrentTimeMillis() - messageStartTime) > MESSAGE_DISPLAY_TIME)
    {
        message = "";
        return;
    }

    int *buffer = lcd->getBuffer();

    // 计算消息框位置和大小
    int fontSize = 24;
    int textLen = message.length();
    int charWidth = fontSize;
    int charHeight = fontSize + 8;

    int textWidth = charWidth * textLen;
    int textHeight = charHeight;

    // 消息框位置(居中)
    int msgBoxX = (LCD_WIDTH - textWidth - 20) / 2;
    int msgBoxY = (LCD_HEIGHT - textHeight - 20) / 2;
    int msgBoxWidth = textWidth + 20;
    int msgBoxHeight = textHeight + 20;

    // 绘制半透明背景
    for (int y = msgBoxY; y < msgBoxY + msgBoxHeight && y < LCD_HEIGHT; y++)
    {
        if (y < 0)
            continue;
        for (int x = msgBoxX; x < msgBoxX + msgBoxWidth && x < LCD_WIDTH; x++)
        {
            if (x < 0)
                continue;
            // 半透明黑色背景
            buffer[y * LCD_WIDTH + x] = 0x80000000 | (buffer[y * LCD_WIDTH + x] & 0x00FFFFFF);
        }
    }

    // 绘制边框
    BMP::drawRectangle(buffer, msgBoxX, msgBoxY, msgBoxX + msgBoxWidth, msgBoxY + msgBoxHeight, 0xFFFFFFFF, 2);

    // 显示文字
    ShowFont::instance()->display(
        const_cast<char *>(message.c_str()),
        fontSize,
        textWidth,
        textHeight,
        0x80000000, // 背景色(透明)
        0x00FFFFFF, // 文字色(白色)
        msgBoxX + 10,
        msgBoxY + 10);
}

// 执行AI走棋
void ChessGame::makeAIMove()
{
    if (!aiStrategy)
        return;
    cout << "AI正在思考..." << endl;
    Move move = aiStrategy->makeMove(*this);
    cout << "AI已选择移动: 从(" << move.from.x() << "," << move.from.y()
         << ") 到 (" << move.to.x() << "," << move.to.y() << ")" << endl;

    // 检查AI是否返回了有效的移动
    if (move.from.x() >= 0 && move.from.y() >= 0 &&
        move.to.x() >= 0 && move.to.y() >= 0 &&
        move.from.x() < BOARD_COLS && move.from.y() < BOARD_ROWS &&
        move.to.x() < BOARD_COLS && move.to.y() < BOARD_ROWS)
    {
        // 确保源位置有棋子且是黑方棋子
        ChessPiece *srcPiece = board[move.from.x()][move.from.y()];
        if (srcPiece && srcPiece->getPieceColor() == Black)
        {
            // 尝试执行移动并检查是否成功
            if (movePiece(move.from.x(), move.from.y(), move.to.x(), move.to.y(), nullptr))
            {
                cout << "AI移动成功: 从(" << move.from.x() << "," << move.from.y()
                     << ") 到 (" << move.to.x() << "," << move.to.y() << ")" << endl;
                switchPlayer();
            }
            else
            {
                // 移动失败
                cout << "AI移动失败" << endl;
            }
        }
        else
        {
            cout << "AI选择的源位置无效或不是黑方棋子" << endl;
        }
    }
    else
    {
        // AI返回了无效坐标
        cout << "AI返回了无效坐标" << endl;
    }
}

void ChessGame::handleNetworkMove(int fromX, int fromY, int toX, int toY)
{
    // 直接移动棋子
    ChessPiece* srcPiece = board[fromX][fromY];
    if(!srcPiece)
    {
        cout<<"源位置没有棋子:("<<fromX<<","<<fromY<<")"<<endl;
        return;
    }
    //如果目标位置有棋子，移除
    ChessPiece* destPiece = board[toX][toY];
    if(destPiece)
    {
        delete destPiece;
    }
    board[toX][toY] = srcPiece;
    board[fromX][fromY] = nullptr;
    srcPiece->setPosition(toX, toY);
    switchPlayer();
    cout<<"收到网络移动:从("<<fromX<<","<<fromY<<")到("<<toX<<","<<toY<<")"<<endl;
}

void ChessGame::sendMoveToNetwork(int fromX, int fromY, int toX, int toY)
{
    ChessPiece* piece = board[fromX][fromY];
    if(piece)
    {
        send_move_data(fromX, fromY, toX, toY, piece->getType(), piece->getPieceColor());
    }
}